package com.itheima.utils;

import com.itheima.common.R;
import com.itheima.common.TokenException;
import com.itheima.enums.RedisEnum;
import com.itheima.enums.TokenErrorEnum;
import io.jsonwebtoken.*;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.Date;

/**
 * Jwt工具类
 *
 * @author 51585
 */
@Component
public class JwtUtil {
    //短token有效时间
    private static long accessTokenExpiration = 24 * 60 * 60 * 1000;
//    private static long accessTokenExpiration =  1000;

    //长token有效时间
    private static long refreshTokenExpiration = 7 * 24 * 60 * 60 * 1000;
//    private static long refreshTokenExpiration = 1000;

    //token私钥，根据此私钥生成对应的token信息
    private static String tokenSignKey = "yeShiMing";

    private static JwtUtil jwtUtil;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @PostConstruct
    public void init() {
        jwtUtil = this;
        jwtUtil.stringRedisTemplate = this.stringRedisTemplate;
    }

    /**
     * 创建User access token
     *
     * @param userId
     * @return
     */
    public static String createStudentAccessToken(String userId) {
        String token = Jwts.builder()
                .setSubject("finally-System")
                .setExpiration(new Date(System.currentTimeMillis() + accessTokenExpiration))
                .claim("userId", userId)
                .signWith(SignatureAlgorithm.HS512, tokenSignKey)
                .compact();
        return token;
    }

    /**
     * 创建User refresh token
     *
     * @param userId
     * @return
     */
    public static String createStudentRefreshToken(String userId) {
        String token = Jwts.builder()
                .setSubject("finally-System")
                .setExpiration(new Date(System.currentTimeMillis() + refreshTokenExpiration))
                .claim("userId", userId)
                .signWith(SignatureAlgorithm.HS512, tokenSignKey)
                .compact();
        return token;
    }

    /**
     * 判断该token格式是否合法
     *
     * @param authToken 携带的token
     * @return
     */
    private static R<String> validateToken(String authToken) {
        try {
            Claims body = Jwts.parser().setSigningKey(tokenSignKey).parseClaimsJws(authToken).getBody();
            String id = (String) body.get("userId");
            String s = jwtUtil.stringRedisTemplate.opsForValue().get(RedisEnum.LOGIN_CHECK.getRedis() + id);
            if (StringUtils.isEmpty(s) || !authToken.equals(s)) {
                return R.error(TokenErrorEnum.ACCOUNT_ALREADY_LOGIN);
            }
            return R.success("success");
        } catch (IllegalArgumentException | MalformedJwtException e) {
            return R.error(TokenErrorEnum.TOKEN_ILLEGAL);
        } catch (ExpiredJwtException e) {
            return R.error(TokenErrorEnum.ACCESS_TOKEN_EXPIRE);
        }
    }

    /**
     * 解析长期token，返回body
     *
     * @param jwt
     * @return
     * @throws Exception
     */
    public static Claims parseRefreshToken(String jwt) throws TokenException {
        Claims body;
        try {
            body = Jwts.parser()
                    .setSigningKey(tokenSignKey)
                    .parseClaimsJws(jwt)
                    .getBody();
        } catch (IllegalArgumentException | MalformedJwtException e) {
            throw new TokenException(TokenErrorEnum.TOKEN_ILLEGAL.name());
        } catch (ExpiredJwtException e) {
            throw new TokenException(TokenErrorEnum.REFRESH_TOKEN_ADVENT.name());
        }
        return body;
    }

    /**
     * 检查token是否可以放行
     *
     * @param token
     * @return
     */
    public static R<String> checkToken(String token) {
        R<String> stringR = validateToken(token);
        if (stringR.getCode() != 1) {
            return stringR;
        }


//        Date expiration = Jwts.parser()
//                .setSigningKey(tokenSignKey)
//                .parseClaimsJws(token)
//                .getBody()
//                .getExpiration();
//        boolean legal = expiration.after(new Date());
//        //没有过期，有效，true
//        if (!legal) {
//            return R.error(TokenErrorEnum.ACCESS_TOKEN_EXPIRE);
//        }
        return R.success("success");
    }

    /**
     * 从token中解析出userId
     *
     * @param token
     * @return
     * @throws Exception
     */
    public static String getUserId(String token) {
        String userId = ((String) Jwts.parser()
                .setSigningKey(tokenSignKey)
                .parseClaimsJws(token)
                .getBody().get("userId"));
        return userId;
    }
}
